/*
 * KKEventAction.cpp
 *
 *  Created on: 2013-9-15
 *      Author: wanghua
 */

#include "KKEventAction.h"
#include "KKDirector.h"

USING_NS_CC;

KKEventAction::KKEventAction() {
	this->m_args = new KKPropertiesDictionary();
}

KKEventAction::~KKEventAction() {
	CC_SAFE_DELETE(m_args);
	CC_SAFE_DELETE(m_action);
}

KKEventAction* KKEventAction::actionWithXml(TiXmlElement* element) {
	KKEventAction* action = new KKEventAction();

	if (action->initWithXml(element)) {
		action->retain();
		action->autorelease();
		return action;
	}

	CC_SAFE_DELETE(action);

	return NULL;
}

bool KKEventAction::initWithXml(TiXmlElement* element) {
	string targetType = element->Attribute("targetType");

	if (targetType == "scene") {
		this->m_targetType = TARGET_SCENE;
	} else if (targetType == "layer") {
		this->m_targetType = TARGET_LAYER;
	} else if (targetType == "sprite") {
		this->m_targetType = TARGET_SPRITE;
	} else if (targetType == "anim") {
		this->m_targetType = TARGET_STORYBOARD;
	} else if (targetType == "sound") {
		this->m_targetType = TARGET_SOUND;
	} else {
		return false;
	}

	string actionType = element->Attribute("actionType");

	if (actionType == "script") {
		this->m_actionType = ACTION_SCRIPT;
	} else if (actionType == "event") {
		this->m_actionType = ACTION_EVENT;
	} else if (actionType == "sound") {
		this->m_actionType = ACTION_SOUND;
	} else if (actionType == "anim") {
		this->m_actionType = ACTION_ANIM;
	} else if (actionType == "status") {
		this->m_actionType = ACTION_STATUS;
	} else if (actionType == "property") {
		this->m_actionType = ACTION_SET_PROPERTY;
	} else {
		return false;
	}

	this->m_action = element->Attribute("action");
	this->m_target = element->Attribute("target");

	if (element->Attribute("id")) {
		m_targetId = atoi(element->Attribute("id"));
	} else {
		m_targetId = -1;
	}

	if (m_targetId == -1 && m_targetType == TARGET_LAYER) {
		CCLog("warn target id of %s is -1\n", m_target);
	}

	TiXmlElement* argElment = element->FirstChildElement("arg");

	while (argElment) {

		const char* k = argElment->Attribute("k");
		const char* v = argElment->Attribute("v");

		if (k) {
			this->m_args->setObject(new CCString(v), k);
		}

		argElment = argElment->NextSiblingElement("arg");
	}

	return true;
}

void KKEventAction::run(KKEventActionArgs* args) {
	KKDirector * mapLayer = KKDirector::shareDirector();

	KKNode* source = NULL;

	if (args) {
		args->setArgs(m_args);

		source = args->getSource();

	} else {
		KKEventActionArgs allargs;
		args = &allargs;
		args->setArgs(m_args);
	}

	if (mapLayer) {

		CCNode * target = NULL;

		KKNode * kknode = NULL;

		switch (this->m_targetType) {

		case TARGET_SCENE:

			target = mapLayer->sceneNamed(this->m_target);

			break;

		case TARGET_LAYER:

		case TARGET_SPRITE:

			if (source) {
				if (source->getId() == this->m_targetId) {
					kknode = source;
				} else {
					kknode = source->findNodeById(this->m_targetId);
				}
			}

			if (!kknode) {
				kknode = mapLayer->findNodeById(this->m_targetId);
			}

			target = dynamic_cast<CCNode*>(kknode);

			break;
		default:
			break;

		}

		if (target) {

			switch (this->m_actionType) {

			case ACTION_SET_PROPERTY:
			case ACTION_SCRIPT:
				mapLayer->executeFunc(target, this->m_action, args);
				break;
			case ACTION_EVENT:
				kknode->performEvent(this->m_action, args);
				break;

			case ACTION_STATUS:

				if (this->m_targetType == TARGET_SPRITE) {
					((KKSprite*) target)->animate(this->m_action,
							this->getIntArg("loop"),
							this->getBooleanArg("fill"));
				} else {
					CCLog("%s is not a kksprite\n", this->m_target);
				}

				break;
			default:
				break;

			}

		} else {

			switch (m_targetType) {

			case TARGET_STORYBOARD:

				if (strcmp(this->m_action, "停止") == 0) {
					mapLayer->stopStoryboard(this->m_target, args);
				} else {
					mapLayer->runStoryboard(this->m_target, args);
				}

				break;

			case TARGET_SOUND:

				if (strcmp(this->m_action, "停止") == 0) {
					mapLayer->stopSound(this->m_target,
							this->getBooleanArg("music"));
				} else {
					mapLayer->playSound(this->m_target,
							this->getBooleanArg("music"),
							this->getBooleanArg("loop") ? -1 : 0);
				}

				break;
			default:
				CCLog("target %s not found \n", m_target);
				break;
			}

		}

	} else {
		CCLog("shareEventHandler is null ");
	}
}

int KKEventAction::getIntArg(string key) {
	CCString* value = m_args->objectForKey(key);
	if (value) {
		return value->intValue();
	}

	return 0;
}

float KKEventAction::getFloatArg(string key) {
	CCString* value = m_args->objectForKey(key);
	if (value) {
		return value->floatValue();
	}

	return 0;
}

bool KKEventAction::getBooleanArg(string key) {
	CCString* value = m_args->objectForKey(key);
	if (value) {
		return value->compare("true") == 0;
	}

	return false;
}

string KKEventAction::getStringArg(string key) {
	CCString* value = m_args->objectForKey(key);
	if (value) {
		return value->getCString();
	}

	return string();
}
